#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>

#include "Block.h"
#include "IInputListener.h"
#include "BlockPlacement.h"
#include <vector>

#pragma warning( disable : 4244; )
// small changes are devastating
std::vector<Block> blocks;
int gridSize = 100;

int getNearestGridX(int x)
{
	if (x%gridSize > (gridSize/2))
	{
		return ((x/gridSize)+1)*gridSize;
	}
	else
	{
		return (x/gridSize)*gridSize;
	}
}

int getNearestGridY(int y)
{
	if (y%gridSize > (gridSize/2))
	{
		return ((y/gridSize)+1)*gridSize;
	}
	else
	{
		return (y/gridSize)*gridSize;
	}
}

void placeBlock(int blockX, int blockY)
{
	Block block;
	block.SetPosition(getNearestGridX(blockX), getNearestGridY(blockY));
	blocks.push_back(block);
}

int main()
{
	sf::RenderWindow app(sf::VideoMode(800, 600, 32), "Blocks");
	app.SetActive();

	sf::View& gameView = app.GetDefaultView();
	sf::View screenView(gameView.GetRect());

	std::vector<IInputListener*> inputListeners;
	inputListeners.push_back(new BlockPlacement(app, placeBlock));
	Block potentialBlock;


	sf::Shape sidebar;
	sf::String sidebarTitle("Components");
	{
		int sidebarWidth = 200;
		double leftOfSidebar = app.GetWidth() - sidebarWidth;
		double bottomOfSidebar = app.GetHeight();
		double rightOfSidebar = app.GetWidth();
		double topOfSidebar = 0;

		sf::Color sidebarFillColor(170, 170, 170);
		sf::Color sidebarOutlineColor(0, 128, 128);
		sidebar.AddPoint(leftOfSidebar, topOfSidebar, sidebarFillColor, sidebarOutlineColor);
		sidebar.AddPoint(leftOfSidebar, bottomOfSidebar, sidebarFillColor, sidebarOutlineColor);
		sidebar.AddPoint(rightOfSidebar, bottomOfSidebar, sidebarFillColor, sidebarOutlineColor);
		sidebar.AddPoint(rightOfSidebar, topOfSidebar, sidebarFillColor, sidebarOutlineColor);

		sidebarTitle.SetColor(sf::Color(255,255,255));
		sidebarTitle.SetCenter(sf::Vector2f(85,20));
		sidebarTitle.SetPosition(sf::Vector2f((leftOfSidebar + rightOfSidebar) / 2.0, topOfSidebar + 20));
	}

	while(app.IsOpened())
	{
		// Update
		sf::Event event;
		while (app.GetEvent(event))
		{
			switch(event.Type)
			{
			case sf::Event::Closed:
				app.Close();
				break;
			case sf::Event::KeyPressed:
				switch(event.Key.Code)
				{
				case sf::Key::Escape:
					app.Close();
					break;
				case sf::Key::A:
					gameView.Move(-gridSize,0);
					break;
				case sf::Key::D:
					gameView.Move(gridSize,0);
					break;
				case sf::Key::W:
					gameView.Move(0,-gridSize);
					break;
				case sf::Key::S:
					gameView.Move(0,gridSize);
					break;
				case sf::Key::X:
					gameView.Zoom(1.1f);
					break;
				case sf::Key::Z:
					gameView.Zoom(1/1.1f);
					break;
				}
				break;
			case sf::Event::Resized:
				break;
			case sf::Event::LostFocus:
				break;
			case sf::Event::GainedFocus:
				break;
			default:
				break;
			}
		}
		const sf::Input& input = app.GetInput();
		for(unsigned int i=0; i<inputListeners.size(); i++)
		{
			inputListeners[i]->parseInput(input);
		}

		// Draw
		app.Clear();

		for(unsigned int i=0; i<blocks.size(); i++)
		{
			app.Draw(blocks[i]);
		}
		
		sf::Vector2f mouseInWorldCoords = app.ConvertCoords(input.GetMouseX(), input.GetMouseY());

		if(input.IsMouseButtonDown(sf::Mouse::Left))
		{
			potentialBlock.SetPosition(getNearestGridX(mouseInWorldCoords.x), getNearestGridY(mouseInWorldCoords.y));
		}
		else
		{
			potentialBlock.SetPosition(mouseInWorldCoords.x, mouseInWorldCoords.y);
		}

		app.Draw(potentialBlock);

		app.SetView(screenView);
		app.Draw(sidebar);
		app.Draw(sidebarTitle);

		app.SetView(gameView);

		app.Display();
	}

	return sizeof(Block);
}
